use uinput_tokio::event::keyboard;

use std::thread;
use tokio;
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use uinput_tokio::device::builder::Builder;
use uinput_tokio::event::controller::Controller::Mouse;
use uinput_tokio::event::controller::Mouse::Left;
use uinput_tokio::event::controller::Mouse::Right;
use uinput_tokio::event::keyboard::Key;
use uinput_tokio::event::relative::Position::{X, Y};
use uinput_tokio::event::relative::Relative::Position;
use uinput_tokio::event::Event::{Controller, Relative};

/// 使用uinput创建一个keyboard虚拟键盘，并等待接受键值
pub async fn loop_block_on_u_keyboard(
    mut rx: UnboundedReceiver<keyboard::Key>,
) -> Result<(), anyhow::Error> {
    match uinput_tokio::default() {
        Ok(build) => {
            let mut device = build
                .name("coolink-keyboard")
                .unwrap()
                .event(uinput_tokio::event::Keyboard::All)
                .unwrap()
                .create()
                .await
                .unwrap();
            while let Some(key) = rx.recv().await {
                tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
                device.click(&key).await.unwrap();
                device.synchronize().await.unwrap();
            }
        }
        Err(err) => {
            log::error!("create uinput keyboard device error:{:?}", err);
            while let Some(key) = rx.recv().await {
                log::warn!("uinput keyboard not create success.");
            }
        }
    }
    Ok(())
}

/// 鼠标事件
pub enum MouseEvent {
    /// 鼠标移动事件
    MouseMove((i32, i32)),
    /// 鼠标左键点击
    MouseLeftClick,
    /// 鼠标右键点击
    MouseRightClick,
}

/// 使用uinput创建一个mouse虚拟鼠标，并等待接受鼠标事件
pub async fn loop_block_on_u_mouse(
    mut rx: UnboundedReceiver<MouseEvent>,
) -> Result<(), anyhow::Error> {
    match uinput_tokio::default() {
        Ok(build) => {
            let mut device = build
                .name("coolink-mouse")
                .unwrap()
                .event(Controller(Mouse(Left)))
                .unwrap() // It's necessary to enable any mouse button. Otherwise Relative events would not work.
                .event(Relative(Position(X)))
                .unwrap()
                .event(Relative(Position(Y)))
                .unwrap()
                .create()
                .await
                .unwrap();
            while let Some(key) = rx.recv().await {
                match key {
                    MouseEvent::MouseMove((x, y)) => {
                        device.send(X, x).await.unwrap();
                        device.send(Y, y).await.unwrap();
                        device.synchronize().await.unwrap();
                    }
                    MouseEvent::MouseLeftClick => {
                        device
                            .click(&uinput_tokio::event::Controller::Mouse(Left))
                            .await
                            .unwrap();
                        device.synchronize().await.unwrap();
                    }
                    MouseEvent::MouseRightClick => {
                        device
                            .click(&uinput_tokio::event::Controller::Mouse(Right))
                            .await
                            .unwrap();
                        device.synchronize().await.unwrap();
                    }
                }
            }
        }
        Err(err) => {
            log::error!("create uinput mouse device error:{:?}", err);
            while let Some(key) = rx.recv().await {
                log::warn!("uinput mouse not create success.");
            }
        }
    }
    Ok(())
}

/// 键值定义
pub struct CoolinkKey {}

/// 按照标准的QWERTY（柯蒂鍵盤）布局定义的按键
impl CoolinkKey {
    pub fn from_str(s: &str) -> Option<Key> {
        match s {
            "Reserved" => Some(Key::Reserved),
            "Esc" => Some(Key::Esc),
            "_1" => Some(Key::_1),
            "_2" => Some(Key::_2),
            "_3" => Some(Key::_3),
            "_4" => Some(Key::_4),
            "_5" => Some(Key::_5),
            "_6" => Some(Key::_6),
            "_7" => Some(Key::_7),
            "_8" => Some(Key::_8),
            "_9" => Some(Key::_9),
            "_0" => Some(Key::_0),
            "Minus" => Some(Key::Minus),
            "Equal" => Some(Key::Equal),
            "BackSpace" => Some(Key::BackSpace),
            "Tab" => Some(Key::Tab),
            "Q" => Some(Key::Q),
            "W" => Some(Key::W),
            "E" => Some(Key::E),
            "R" => Some(Key::R),
            "T" => Some(Key::T),
            "Y" => Some(Key::Y),
            "U" => Some(Key::U),
            "I" => Some(Key::I),
            "O" => Some(Key::O),
            "P" => Some(Key::P),
            "LeftBrace" => Some(Key::LeftBrace),
            "RightBrace" => Some(Key::RightBrace),
            "Enter" => Some(Key::Enter),
            "LeftControl" => Some(Key::LeftControl),
            "A" => Some(Key::A),
            "S" => Some(Key::S),
            "D" => Some(Key::D),
            "F" => Some(Key::F),
            "G" => Some(Key::G),
            "H" => Some(Key::H),
            "J" => Some(Key::J),
            "K" => Some(Key::K),
            "L" => Some(Key::L),
            "SemiColon" => Some(Key::SemiColon),
            "Apostrophe" => Some(Key::Apostrophe),
            "Grave" => Some(Key::Grave),
            "LeftShift" => Some(Key::LeftShift),
            "BackSlash" => Some(Key::BackSlash),
            "Z" => Some(Key::Z),
            "X" => Some(Key::X),
            "C" => Some(Key::C),
            "V" => Some(Key::V),
            "B" => Some(Key::B),
            "N" => Some(Key::N),
            "M" => Some(Key::M),
            "Comma" => Some(Key::Comma),
            "Dot" => Some(Key::Dot),
            "Slash" => Some(Key::Slash),
            "RightShift" => Some(Key::RightShift),
            "LeftAlt" => Some(Key::LeftAlt),
            "Space" => Some(Key::Space),
            "CapsLock" => Some(Key::CapsLock),
            "F1" => Some(Key::F1),
            "F2" => Some(Key::F2),
            "F3" => Some(Key::F3),
            "F4" => Some(Key::F4),
            "F5" => Some(Key::F5),
            "F6" => Some(Key::F6),
            "F7" => Some(Key::F7),
            "F8" => Some(Key::F8),
            "F9" => Some(Key::F9),
            "F10" => Some(Key::F10),
            "NumLock" => Some(Key::NumLock),
            "ScrollLock" => Some(Key::ScrollLock),
            "F11" => Some(Key::F11),
            "F12" => Some(Key::F12),
            "RightControl" => Some(Key::RightControl),
            "SysRq" => Some(Key::SysRq),
            "RightAlt" => Some(Key::RightAlt),
            "LineFeed" => Some(Key::LineFeed),
            "Home" => Some(Key::Home),
            "Up" => Some(Key::Up),
            "PageUp" => Some(Key::PageUp),
            "Left" => Some(Key::Left),
            "Right" => Some(Key::Right),
            "End" => Some(Key::End),
            "Down" => Some(Key::Down),
            "PageDown" => Some(Key::PageDown),
            "Insert" => Some(Key::Insert),
            "Delete" => Some(Key::Delete),
            "LeftMeta" => Some(Key::LeftMeta),
            "RightMeta" => Some(Key::RightMeta),
            "ScrollUp" => Some(Key::ScrollUp),
            "ScrollDown" => Some(Key::ScrollDown),
            "F13" => Some(Key::F13),
            "F14" => Some(Key::F14),
            "F15" => Some(Key::F15),
            "F16" => Some(Key::F16),
            "F17" => Some(Key::F17),
            "F18" => Some(Key::F18),
            "F19" => Some(Key::F19),
            "F20" => Some(Key::F20),
            "F21" => Some(Key::F21),
            "F22" => Some(Key::F22),
            "F23" => Some(Key::F23),
            "F24" => Some(Key::F24),
            _ => None,
        }
    }
}
